using System;
using System.Data;
using System.Windows.Forms;

using System.IO;
using TaskPluginInterface;

namespace TaskPluginTest
{
    /// <summary>
    /// The application for testing the plugins
    /// </summary>
    public partial class PluginTestForm : Form
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="PluginTestForm"/> class.
        /// </summary>
        public PluginTestForm()
        {
            InitializeComponent();
        }

        #region Private Variables

        private ITaskPlugin _activePlugin;
        private const string DEFAULT_PLUGIN_FOLDER = "Plugins";
        private bool _cancel;
        private bool _pluginExecuting;

        // Other Variables
        private readonly log4net.ILog _log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        #endregion Private Variables

        #region Events

        #region Button Events

        private void btnBrowseFolder_Click(object sender, EventArgs e)
        {
            fldBrowser.SelectedPath = Path.Combine(Application.StartupPath, "Plugins");
            DialogResult result = fldBrowser.ShowDialog();

            if (result != DialogResult.Cancel)
            {
                txtFolder.Text = fldBrowser.SelectedPath;
                cboPlugin.DataSource = null;
                cboPluginFiles.DataSource = null;
                clearPluginInfo();
            }
        }

        private void btnLoadPlugins_Click(object sender, EventArgs e)
        {
            // Reload the files that contain Plugins.
            if (Directory.Exists(txtFolder.Text))
            {
                listPlugins(txtFolder.Text);
            }
        }

        private void btnExecute_Click(object sender, EventArgs e)
        {
            if (_activePlugin != null)
            {
                try
                {
                    _cancel = false;

                    enableForm(false);

                    taskProgress.Value = 0;
                    itemProgress.Value = 0;
                    lblMessage.Text = "";

                    _pluginExecuting = true;
                    ExecuteResult result = _activePlugin.Execute();
                    _pluginExecuting = false;
                    MessageBox.Show(string.Format("The result of Execute was '{0}'", Enum.GetName(typeof(ExecuteResult), result)), "Executed Task!", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString(), "Error executing the task!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    enableForm(true);
                }
            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            _cancel = true;
        }
        #endregion Button Events

        #region ComboBox Events

        private void cboPluginTypes_SelectedIndexChanged(object sender, EventArgs e)
        {
            listPlugins(txtFolder.Text);
        }

        private void cboPluginFiles_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Need to get the list of Plugins from the file
            clearPluginInfo();

            cboPlugin.DataSource = null;

            if (cboPluginFiles.SelectedItem != null)
            {
                cboPlugin.DataSource = Utilities.GetPlugins(((FileInfo)cboPluginFiles.SelectedItem).FullName);
                cboPlugin.DisplayMember = "Name";
            }
        }

        private void cboPlugin_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Need to load the plug-in information
            clearPluginInfo();

            if (cboPlugin.SelectedItem != null)
            {
                displayPluginInfo(cboPluginFiles.SelectedItem.ToString(), cboPlugin.SelectedItem.ToString());
            }

        }

        #endregion ComboBox Events

        #region Form Events

        private void frmMain_Load(object sender, EventArgs e)
        {
            fldBrowser.RootFolder = Environment.SpecialFolder.MyComputer;

            string pluginFolder = Utilities.GetPluginFolder(DEFAULT_PLUGIN_FOLDER);

            fldBrowser.SelectedPath = pluginFolder;
            txtFolder.Text = fldBrowser.SelectedPath;

            cboPluginTypes.Items.AddRange(Enum.GetNames(typeof(PluginType)));
            cboPluginTypes.Items.Add("All");
            cboPluginTypes.SelectedItem = "All";

            Icon = Properties.Resources.TaskPluginTest;

        }

        void frmMain_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            if (_pluginExecuting)
                _cancel = true;
        }

        #endregion Form Events

        #endregion Events

        #region ITaskPlugin Events

        void activePlugin_EventProcessing(object sender, PluginEventArgs e)
        {
            e.Cancel = _cancel;
            refreshProgress(e);
        }

        void activePlugin_EventExceptionOccurred(object sender, PluginEventArgs e)
        {
            refreshProgress(e);
            MessageBox.Show(e.RaisedException.ToString(), "Error executing the task!", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        void activePlugin_EventStart(object sender, PluginEventArgs e)
        {
            refreshProgress(e);
        }

        void activePlugin_EventEnd(object sender, PluginEventArgs e)
        {
            refreshProgress(e);
        }

        void refreshProgress(PluginEventArgs e)
        {
            if (e.Progress.TotalTasks == 0)
            {
                taskProgress.Value = 0;
            }
            else
            {
                taskProgress.Maximum = e.Progress.TotalTasks;
                taskProgress.Value = e.Progress.CurrentTask;
                string msg = string.Format("Working on task {0} of {1}.", taskProgress.Value, taskProgress.Maximum);
                tt.SetToolTip(taskProgress, msg);
            }

            if (e.Progress.TotalItems == 0)
            {
                itemProgress.Value = 0;
            }
            else
            {
                itemProgress.Maximum = e.Progress.TotalItems;
                itemProgress.Value = e.Progress.CurrentItem;
                string msg = string.Format("Working on item {0} of {1}.", itemProgress.Value, itemProgress.Maximum);
                tt.SetToolTip(itemProgress, msg);
            }

            lblMessage.Text = string.IsNullOrEmpty(e.Message) ? "" : e.Message;

            itemProgress.Refresh();
            taskProgress.Refresh();
            Application.DoEvents();
        }
        #endregion ITaskPlugin Events

        #region Helper Methods

        /// <summary>
        /// Populates the combo box with a list of valid Plugins.
        /// </summary>
        /// <param name="folder">The folder in which you want to get a plug-in list</param>
        private void listPlugins(string folder)
        {
            clearPluginInfo();

            cboPluginFiles.DataSource = null;
            cboPlugin.DataSource = null;

            if (Directory.Exists(folder) == false)
            {
                return;
            }

            if (cboPluginTypes.SelectedItem != null)
            {
                string pluginTypeName = cboPluginTypes.SelectedItem.ToString();
                {
                    if (pluginTypeName == "All")
                    {
                        cboPluginFiles.DataSource = Utilities.GetPluginFileList(folder);
                    }
                    else
                    {
                        PluginType pluginType = (PluginType)Enum.Parse(typeof(PluginType), pluginTypeName);
                        cboPluginFiles.DataSource = Utilities.GetPluginFileList(folder, pluginType);
                    }
                }
            }
            cboPluginFiles.DisplayMember = "Name";

        }

        /// <summary>
        /// Enables or disables the controls on the form
        /// </summary>
        /// <param name="onOrNot">True to enable the form. False to disable it.</param>
        private void enableForm(bool onOrNot)
        {

            if (onOrNot == false)
            {
                Cursor = Cursors.WaitCursor;
            }

            txtFolder.Enabled = onOrNot;
            btnBrowseFolder.Enabled = onOrNot;
            btnLoadPlugins.Enabled = onOrNot;
            btnExecute.Enabled = onOrNot;
            cboPluginTypes.Enabled = onOrNot;
            cboPluginFiles.Enabled = onOrNot;
            cboPlugin.Enabled = onOrNot;
            grdSchedule.Enabled = onOrNot;

            btnCancel.Enabled = !onOrNot;

            if (onOrNot)
            {
                Cursor = Cursors.Default;
            }
        }

        /// <summary>
        /// Clears the plug-in information from the labels
        /// </summary>
        private void clearPluginInfo()
        {
            lblName.Text = "";
            lblDescription.Text = "";
            lblExtension.Text = "";
            lblVersion.Text = "";
            lblAuthor.Text = "";
            lblExtensionDescription.Text = "";
            grdSchedule.DataSource = null;
            taskProgress.Value = 0;
            itemProgress.Value = 0;

            taskProgress.Refresh();
            itemProgress.Refresh();
        }

        #endregion Helper Methods

        #region ITaskPlugin Methods

        /// <summary>
        /// Displays the plug-in information.
        /// </summary>
        /// <param name="filename">The filename that contains the Plugin</param>
        /// <param name="className">The class name to load</param>
        private void displayPluginInfo(string filename, string className)
        {

            ITaskPlugin plugin = Utilities.GetPlugin(filename, className);

            lblMessage.Text = "";
            taskProgress.Value = 0;

            if (plugin != null)
            {
                _activePlugin = plugin;
                lblName.Text = plugin.Name;
                lblDescription.Text = plugin.Description;
                lblExtension.Text = plugin.Extension;
                lblExtensionDescription.Text = plugin.ExtensionDescription;
                lblVersion.Text = plugin.Version;
                lblAuthor.Text = plugin.Author;

                if (plugin.Extension != "")
                {
                    ofd.Filter = string.Format("{0} files ({1})|{1}|All Files (*.*)|*.*", plugin.ExtensionDescription, plugin.Extension);
                    ofd.FilterIndex = 0;
                }
                else
                {
                    ofd.Filter = "All Files (*.*)|*.*";
                    ofd.FilterIndex = 0;
                }


                // /Load the Schedule
                DataSet ds = new DataSet();
                DataTable dt = ds.Tables.Add("Parameters");
                dt.Columns.Add(new DataColumn("Type", typeof(Type)));
                dt.Columns.Add(new DataColumn("Date", typeof(DateTime)));


                foreach (Schedule.IScheduledItem schedule in plugin.Schedule)
                {
                    DataRow dr = dt.NewRow();
                    dr["Type"] = schedule.GetType();
                    dr["Date"] = schedule.NextRunTime(DateTime.Now, false);
                    dt.Rows.Add(dr);
                }

                grdSchedule.DataSource = dt;

                // Attach the events
                _activePlugin.EventEnd += activePlugin_EventEnd;
                _activePlugin.EventStart += activePlugin_EventStart;
                _activePlugin.EventExceptionOccurred += activePlugin_EventExceptionOccurred;
                _activePlugin.EventProcessing += activePlugin_EventProcessing;

            }

        }

        #endregion ITaskPlugin Methods


    }
}